package cn.ppool.xmlmapper.utils;


import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.reflect.FieldUtils;;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;


@Log4j2
public class MapBeanUtil {


    /**
     * map转bean
     *
     * @param map
     * @param clazz
     * @param <T>
     * @return
     * @throws Exception
     */
    public static <T> List<T> transMap2Bean(List<Map> map, Class<T> clazz) throws Exception {
        List<T> list = new LinkedList<>();
        for (Map ss : map) {
            list.add(transMap2Bean(ss, clazz));
        }
        return list;
    }


    /**
     * Map转对象
     *
     * @param map
     * @param clazz
     * @param <T>
     * @return
     * @throws Exception
     */
    public static <T> T transMap2Bean(Map map, Class<T> clazz) throws Exception {
        List<Field> ss = FieldUtils.getAllFieldsList(clazz);
        T kk = clazz.newInstance();
        for (Field f : ss) {
            String key = f.getName();
            //默认字段
            if (key.equals("serialVersionUID")) continue;
            if (key.equals("class")) continue;
            //
            if (map.containsKey(key)) {
                if (map.get(key) == null) continue;
                PropertyDescriptor property = new PropertyDescriptor(key, clazz);
                Method setter = property.getWriteMethod();
                if (property.getPropertyType().isEnum()) {//enum
                    List<Field> assd = FieldUtils.getAllFieldsList(Class.forName(property.getPropertyType().getName()));
                    for (Field ff : assd) {
                        if (map.get(key).equals(ff.getName())) {
                            setter.invoke(kk, ff.get(ff.getName()));
                            break;
                        }
                    }
                } else {
                    switch (property.getPropertyType().getName()) {
                        case "java.lang.Integer":
                            setter.invoke(kk, Integer.valueOf(String.valueOf(map.get(key))));
                            break;
                        case "java.lang.Long":
                            setter.invoke(kk, Long.parseLong(String.valueOf(map.get(key))));
                            break;
                        case "java.lang.Double":
                            setter.invoke(kk, Double.valueOf(String.valueOf(map.get(key))));
                            break;
                        default:
                            try {
                                setter.invoke(kk, map.get(key));
                            } catch (Exception ex) {
                                log.error("transMap2Bean:" + key, ex);
                                throw new RuntimeException("ERROR");
                            }
                            break;
                    }
                }
            }
        }
        return kk;
    }


    /**
     * 对象转map
     *
     * @param obj
     * @return
     * @throws Exception
     */
    public static Map objectToMap(Object obj) {
        if (obj == null) {
            return null;
        }
        Map<String, Object> map = new HashMap<String, Object>();
        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for (PropertyDescriptor property : propertyDescriptors) {
                String key = property.getName();
                // 过滤class属性
                if (!key.equals("class")) {
                    // 得到property对应的getter方法
                    Method getter = property.getReadMethod();
                    Object value = getter.invoke(obj);
                    map.put(key, value);
                }
            }
        } catch (Exception e) {
            log.error(e);
        }
        return map;
    }


}
